<template>
  <div class="tag-selector">
    <template v-for="level1Tag in dataList" :key="level1Tag.id">
      <div class="level1-container">
        <div class="level1-title">{{ level1Tag.tagName }}：</div>
        <div class="level1-children">
            <div class="level2-list">
                <a-checkable-tag
                    v-for="level2Tag in level1Tag.children"
                    :bordered="false"
                    :key="level2Tag.id"
                    :checked="level2Tag.checked"
                    @change="() => handleLevel2TagChange(level1Tag, level2Tag.id)"
                >
                    {{ level2Tag.tagName }}
                    <CaretUpOutlined v-if="!level2Tag.expanded" />
                    <CaretDownOutlined v-if="level2Tag.expanded" />
                </a-checkable-tag>
            </div>
            <template v-for="level2Tag in level1Tag.children" :key="level2Tag.id">
                <a-divider v-if="level2Tag.expanded && (level2Tag.children && level2Tag.children.length > 0)" class="level2-divider"></a-divider>
                <div v-if="level2Tag.expanded && (level2Tag.children && level2Tag.children.length > 0)" class="level3-list">
                    <a-checkable-tag
                        :bordered="false"
                        :checked="isAllLevel3TagsChecked(level2Tag)"
                        @change="(checked) => handleAllLevel3TagsChange(level2Tag, checked)"
                    >
                        全部
                    </a-checkable-tag>
                    <a-checkable-tag
                        :bordered="false"
                        v-for="level3Tag in level2Tag.children"
                        :key="level3Tag.id"
                        :checked="isLevel3TagChecked(level3Tag.id)"
                        @change="(checked) => handleLevel3TagChange(level2Tag, level3Tag, checked)"
                    >
                        {{ level3Tag.tagName }}
                        <CloseCircleFilled v-if="level3Tag.checked" />
                    </a-checkable-tag>
                </div>
                <a-divider v-if="level2Tag.expanded && (level2Tag.children && level2Tag.children.length > 0)" class="level2-divider"></a-divider>
            </template>
        </div>
      </div>
    </template>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, watch } from 'vue';
import { CaretUpOutlined, CaretDownOutlined, CloseCircleFilled } from '@ant-design/icons-vue';
import { isNotEmpty } from "@/utils";
import { Tag } from '@/models/tag';

export default defineComponent({
  name: 'TagSelector',
  components: {
    CaretUpOutlined,
    CaretDownOutlined,
    CloseCircleFilled,
  },
  props: {
    tags: {
      type: Array as () => Tag[],
      required: true,
    },
    checkedTagIds: {
      type: Array as () => number[],
      default: () => [],
    },
  },
  setup(props, { emit }) {
    const newCheckedTagIds = ref([...props.checkedTagIds]);

    const isLevel2TagChecked = (tagId: number) => {
      return newCheckedTagIds.value.includes(tagId);
    };

    const isLevel3TagChecked = (tagId: number) => {
      return newCheckedTagIds.value.includes(tagId);
    };

    const isAllLevel3TagsChecked = (level2Tag: Tag) => {
      if (!level2Tag.children) return false;

      return level2Tag.children.every((tag) => newCheckedTagIds.value.includes(tag.id));
    };

    const handleLevel2TagChange = (level1Tag: Tag, level2TagId: number) => {
      if (!level1Tag) return;

      level1Tag.children?.forEach((level2Tag) => {
        level2Tag.expanded = (level2Tag.id === level2TagId) ? !level2Tag.expanded : false;
      });

      level1Tag.expanded = level1Tag.children?.some((tag) => tag.expanded);
    };

    const handleLevel3TagChange = (level2Tag: Tag, level3Tag: Tag, checked: boolean) => {
      level3Tag.checked = checked;

      if (checked) {
        newCheckedTagIds.value.push(level3Tag.id);
        level2Tag.checked = true;
      } else {
        newCheckedTagIds.value = newCheckedTagIds.value.filter((id) => id !== level3Tag.id);
        level2Tag.checked = level2Tag.children?.some((tag) => (level3Tag.id===tag.id) ? checked : newCheckedTagIds.value.includes(tag.id));
      }

      emit('update:checkedTagIds', newCheckedTagIds.value);
    };

    const handleAllLevel3TagsChange = (level2Tag: Tag, checked: boolean) => {
      level2Tag.checked = checked;
      level2Tag.children?.forEach((tag) => {
        tag.checked = checked;
      });

      if (checked) {
        level2Tag.children?.forEach((tag) => {
          if (!newCheckedTagIds.value.includes(tag.id)) {
            newCheckedTagIds.value.push(tag.id);
          }
        });
      } else {
        newCheckedTagIds.value = newCheckedTagIds.value.filter((id) => !level2Tag.children?.some((tag) => tag.id === id));
      }

      emit('update:checkedTagIds', newCheckedTagIds.value);
    };

    // 初始化数据
    const dataList = ref<Tag[]>([]);
    const initData = () => {
      // console.log('TagSelector Tags:', props.tags); // 调试信息
      let newLevel1Tags = [] as Tag[];
      props.tags.forEach((level1Tag) => {
        // 若有2级标签
        if (isNotEmpty(level1Tag.children)) {
          let newLevel2Tags = [] as Tag[];

          level1Tag.children.forEach((level2Tag) => {
            // 若有3级标签
            if (isNotEmpty(level2Tag.children)) {
              let level2TagChecked = false;
              
              let newLevel3Tags = [] as Tag[];
              for (let level3Tag of level2Tag.children) {
                let level3TagChecked = newCheckedTagIds.value.includes(level3Tag.id);
                if (level3TagChecked) {
                  level2TagChecked = true;
                }

                newLevel3Tags.push({
                  ...level3Tag,
                  checked: level3TagChecked,
                  expanded: level3TagChecked,
                });
              }

              newLevel2Tags.push({
                ...level2Tag,
                checked: level2TagChecked,
                expanded: false,
                children: newLevel3Tags,
              });
            } else {
              newLevel2Tags.push({
                ...level2Tag,
                checked: false,
                expanded: false,
              });
            }
          });

          if (isNotEmpty(newLevel2Tags)) {
            newLevel1Tags.push({
              ...level1Tag,
              checked: false,
              expanded: false,
              children: newLevel2Tags,
            });
          }
        } else {
          newLevel1Tags.push({
            ...level1Tag,
            checked: false,
            expanded: false,
          });
        }
      });

      dataList.value = newLevel1Tags;
    };

    // 监听 tags 的变化
    watch(() => props.tags, () => {
      initData();
    }, { immediate: true });

    return {
      dataList,
      isLevel2TagChecked,
      isLevel3TagChecked,
      isAllLevel3TagsChecked,
      handleLevel2TagChange,
      handleLevel3TagChange,
      handleAllLevel3TagsChange,
    };
  },
});
</script>

<style lang="less" scoped>
.tag-selector {
  display: flex;
  flex-direction: column;

  .level1-container > :not(:last-child) {
    margin-bottom: 20px;
  }

  .level1-container {
    display: flex;
    flex-direction: row;

    .level1-title {
      height: 32px;
      line-height: 32px;
      font-size: 16px;
      font-weight: 500;
      color: @font-black;
    }

    .level1-children {
      flex: 1;
      display: flex;
      flex-direction: column;
      margin-left: 6px;

      .level2-list {
        line-height: 32px;
      }

      .level3-list {
        line-height: 32px;
      }

      :deep(.ant-tag) {
        color: @font-grey;
        font-size: 16px;
        font-weight: 400;
        

        &.ant-tag-checkable-checked {
          color: #ed171f;
          font-weight: 500;
          background-color: transparent;
        }

        &.ant-tag-checkable-checked:hover {
          background-color: transparent;
        }

        .anticon {
          width: 12px;
          height: 12px;
        }
      }

      :deep(.ant-divider-horizontal) {
        margin: 8px 0;
      }
    }
  }
}
</style>